home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Skunkware 5
/
Skunkware 5.iso
/
src
/
Games
/
net3d-0.08
/
game.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-06-22
|
28KB
|
1,163 lines
/* game.c
*
* gameplay related functions
*/
#include "net3d.h"
static int gkeys[]={XK_Left, XK_Right, XK_Up, XK_Down, XK_a,
XK_z, XK_s, XK_o, XK_p, XK_Return, XK_q,
XK_w,XK_l,XK_j,XK_b,XK_i,XK_k};
char fakepipe[1000]; /* place single-player mode messages
* go through. */
bool buildicons = false; /* is the build icons bar open? */
static int wallcost[]={0,2,2, 3,3,3,3, 4,4,4,4, 4, 3, 6};
/* costs of the various wall sections */
int ctrlc = 0; /* has control-c been hit? */
/* read 0 or more keyboard events, and for each either transmit a
* message to the server or change the viewing mode
*/
void readkeys(int *vmode, struct vehicle *drive,struct vehicle *vh,
double ctime)
{
XEvent event; /* message from X */
KeySym key; /* key pressed */
int keyread;
double velocity; /* motion attributes */
double angle;
double altitude;
double tangle;
double turret_ang;
static double movefactor = 1; /* if a key is held down, then the angle
* change factor is increased until a frame
* in which no key is pressed. */
Bool keyhit = False;
char msg[1200]=""; /* complete message to send */
/* In single player mode, instead of using file descriptors to pass
* commands between readkeys() and readnet(), the string fakepipe
* is used to store commands intermediately.
*/
if (singlep) {
sprintf(fakepipe,"%f ",gametime());
}
/* extract attribute from vehicle, for storing into temporary
* variables (if the player is alive).
*/
if (drive) {
velocity = drive->velocity;
angle = drive->angle;
altitude = drive->parts[0]->pos.z;
tangle = findturret(drive) ? findturret(drive)->angle : 0.0;
turret_ang = drive->turret_ang;
}
/* If control-c is hit, explode this player, close the game window and
* fork off a new process to convince the server that this player is still
* around. This prevents one player ending the game for everyone by breaking
* their client process.
*/
if (ctrlc) {
if (drive)
nprintf(sock,"x %d 0.0\nd\n",drive->vid);
XDestroyWindow(display,view_win);
XFreePixmap(display,view_pm);
XFlush(display);
if (fork())
exit(0);
else
deadloop();
}
while(XPending(display)) {
char com[100]=""; /* one command */
XNextEvent(display,&event);
/*
printf("got event %d\n",event.type);
*/
switch(event.type) {
case KeyPress:
keyhit = True;
if (movefactor < 20)
movefactor += 1.0;
if (!drive) {
/* The player is dead, so forget about any keypress
* events.
*/
break;
}
key = XLookupKeysym(&event.xkey,0);
keyread = key;
/* printf("keyread = %d\n",keyread); */
/* A change in the view mode */
if (keyread==XK_1) {
*vmode=1;
}
else if (keyread==XK_2) {
*vmode=2;
}
else if (keyread==XK_3) {
*vmode=3;
}
else if (keyread==XK_4) {
*vmode=4;
}
else if (keyread==XK_5) {
*vmode=5;
}
else if (keyread==XK_6) {
*vmode=6;
}
else if (keyread==XK_7) {
*vmode=7;
}
else if (keyread==XK_8) {
*vmode=8;
}
else if (keyread==XK_9) {
struct vehicle *cv=NULL;
*vmode=9;
/* Find the next possible interesting vehicle to
* view from.
*/
/* first find the current one.. */
if (drive->vm9vid != -1) {
cv = findbyvid(vh,drive->vm9vid);
}
if (!cv) {
/* Current one has been destroyed! */
cv = vh;
}
/* now find the next suitable target */
do {
cv = cv->next;
if (!cv) {
/* run off end of list.. */
cv=vh;
}
} while(boring(cv));
drive->vm9vid = cv->vid;
}
else if (keyread==gkeys[11]) {
/* change to wireframe mode */
wireframe = !wireframe;
}
else if (keyread==gkeys[0]) {
/* left turn */
angle -= DELTA_ANGLE * movefactor;
sprintf(com,"a %d %f",drive->vid,angle);
}
else if (keyread==gkeys[1]) {
/* right turn */
angle += DELTA_ANGLE * movefactor;
sprintf(com,"a %d %f",drive->vid,angle);
}
else if (keyread==gkeys[2]) {
/* accellerate */
velocity += DELTA_VELOCITY;
velocity = min(drive->max.velocity,velocity);
sprintf(com,"v %d %f",drive->vid,velocity);
}
else if (keyread==gkeys[3]) {
/* decellerate */
velocity -= DELTA_VELOCITY;
velocity = max(-drive->max.velocity,velocity);
sprintf(com,"v %d %f",drive->vid,velocity);
}
else if (keyread==gkeys[4] && drive->flying) {
/* increase altitude */
altitude += DELTA_ALT * movefactor;
sprintf(com,"c %d %f",drive->vid,altitude);
}
else if (keyread==gkeys[5] && drive->flying) {
/* decrease altitude */
altitude -= DELTA_ALT * movefactor;
sprintf(com,"c %d %f",drive->vid,altitude);
}
else if (keyread==gkeys[6]) {
/* come to a complete halt */
velocity = 0.0;
sprintf(com,"v %d 0.0",drive->vid);
}
else if (keyread==gkeys[7]) {
/* rotate gun left */
tangle -= DELTA_ANGLE * movefactor;
sprintf(com,"t %d %f",drive->vid,tangle);
}
else if (keyread==gkeys[8]) {
/* rotate gun right */
tangle += DELTA_ANGLE * movefactor;
sprintf(com,"t %d %f",drive->vid,tangle);
}
else if (keyread==gkeys[9]) {
/* fire gun */
sprintf(com,"f %d 0.0",drive->vid);
}
else if (keyread==gkeys[10]) {
/* quit game */
sprintf(com,"x %d 0.0",drive->vid);
}
else if (keyread==gkeys[12] && (*vmode==4 || *vmode==6)) {
/* attempt lock onto a target.
* The calculation of which vehicles the lock
* is made on is done now, and the victim
* transmitted to all clients.
*/
int victim=-1;
struct vehicle *vpos;
float cdist=VIEW_RANGE;
/* find the closest vehicle within 20 units
* of the line of sight from the player.
*/
for(vpos=vh; vpos; vpos=vpos->next) {
struct object *ob;
int j;
if (vpos==drive || vpos->type==t_scenery)
continue;
for(j=0; j<vpos->partcount; j++) {
int k;
ob=vpos->parts[j];
for(k=0; k<ob->pcount; k++) {
float x,y,z;
x=ob->cpoints[k].x;
y=ob->cpoints[k].y;
z=ob->cpoints[k].z;
if (z>0 && z<cdist &&
(x*x + y*y)<20*20) {
victim=vpos->vid;
cdist=z;
}
}
}
}
sprintf(com,"l %d %d",drive->vid,victim);
}
else if (keyread==gkeys[13]) {
if (drive->type == t_tank || drive->type == t_hover ||
drive->type == t_fixedwing) {
/* leave vehicle */
sprintf(com,"j %d 0.0",drive->vid);
}
}
else if (keyread==gkeys[14]) {
/* Toggle build icon bar */
buildicons = !buildicons;
}
else if (keyread==gkeys[15]) {
/* weapon tilted up */
turret_ang += DELTA_TURRET_ANG;
turret_ang = min(turret_ang,drive->max.turret_ang);
sprintf(com,"r %d %f",drive->vid,turret_ang);
}
else if (keyread==gkeys[16]) {
/* weapon tilted down */
turret_ang -= DELTA_TURRET_ANG;
turret_ang = max(turret_ang,-drive->max.turret_ang);
sprintf(com,"r %d %f",drive->vid,turret_ang);
}
break;
case ConfigureNotify:
if (event.xconfigure.width != window_w ||
event.xconfigure.height != window_h) {
/* change in window size */
window_w=event.xconfigure.width;
window_h=event.xconfigure.height;
/* free old back buffer pixmap, and create
* a new one.
*/
XFreePixmap(display,view_pm);
view_pm=XCreatePixmap(display,view_win,
window_w,window_h,8);
}
break;
case ButtonPress:
if (!drive) {
/* The player is dead. Ignore any button presses. */
break;
}
switch(event.xbutton.button) {
case Button1:
if (event.xbutton.y > window_h-16 &&
event.xbutton.x < 13*16) {
/* Send a build message */
sprintf(com,"b %d %d\n",drive->vid,
(event.xbutton.x/16)+1);
}
break;
}
break;
default:
/* some other x-event */
break;
}
/* concatentate command from this event with list of commands
* to send to server */
strcat(msg,com);
strcat(msg," ");
}
/* if no key has been hit this frame, lower move multiplier */
if (!keyhit && movefactor > 1)
movefactor -= 0.5;
/* send off all commands to server (if the player is alive).
*/
if (singlep) {
/* Fake the fd method of passing commands when in single player
* mode. */
strcat(fakepipe,msg);
}
else
nprintf(sock,"%s\n",msg);
}
void createcamera(struct vehicle *drive, struct view *vw, int vmode,
struct map *mp, struct vehicle *vhead)
{
double gun_angle;
struct object *tur;
struct vehicle *v=NULL;
switch(vmode) {
case 1:
/* looking at vehicle, from far away */
vw->vrp.x=drive->parts[0]->pos.x + 200;
vw->vrp.y=drive->parts[0]->pos.y + 200;
vw->vrp.z=drive->parts[0]->pos.z + 200;
/* towards vehicle */
vw->n.x=-200;
vw->n.y=-200;
vw->n.z=-200;
/* up vector vertical */
vw->v.x=0; vw->v.y=0; vw->v.z=1;
break;
case 2:
/* looking at your vehicle, from the map lookout position */
vw->vrp.x = mp->lookout.x;
vw->vrp.y = mp->lookout.y;
vw->vrp.z = mp->lookout.z;
/* towards vehicle */
vw->n.x = drive->parts[0]->pos.x - mp->lookout.x;
vw->n.y = drive->parts[0]->pos.y - mp->lookout.y;
vw->n.z = drive->parts[0]->pos.z - mp->lookout.z;
vw->v.x=0; vw->v.y=0; vw->v.z=1;
if (!vw->n.x && !vw->n.y && !vw->n.z) {
/* uh-oh! the vehicle is exactly at the point of the camera! */
vw->n.y = 1.0;
vw->v.x = 1.0;
}
else if (!vw->n.x && !vw->n.y) {
/* uh-oh! u and v are parrellel! */
vw->v.x = 1.0;
}
break;
case 3:
/* looking from just behind vehicle */
vw->vrp.x = drive->parts[0]->pos.x - jcos(drive->angle)*70 + 10;
vw->vrp.y = drive->parts[0]->pos.y - jsin(drive->angle)*70;
vw->vrp.z = drive->parts[0]->pos.z + 60;
vw->n.x = jcos(drive->angle)*10;
vw->n.y = jsin(drive->angle)*10;
vw->n.z = -5;
vw->v.x=0; vw->v.y=0; vw->v.z=1;
break;
case 4:
/* inside vehicle */
vw->vrp.x = drive->parts[0]->pos.x;
vw->vrp.y = drive->parts[0]->pos.y;
vw->vrp.z = drive->parts[0]->pos.z+5;
/* in direction of travel */
vw->n.x = jcos(drive->angle);
vw->n.y = jsin(drive->angle);
vw->n.z = 0;
vw->v.x=0; vw->v.y=0; vw->v.z=1;
break;
case 5:
/* directly above vehicle */
vw->vrp.x = drive->parts[0]->pos.x;
vw->vrp.y = drive->parts[0]->pos.y;
vw->vrp.z = drive->parts[0]->pos.z + 200;
/* looking down onto it */
vw->n.x = 0;
vw->n.y = 0;
vw->n.z = -1;
vw->v.x = 1; vw->v.y = 0; vw->v.z = 0;
break;
case 6:
/* gun turret view */
tur = findturret(drive);
if (!tur) {
/* no gun turret found */
gun_angle = drive->angle;
tur = drive->parts[0];
}
else {
/* vehicle has a gun turret */
gun_angle = tur->angle;
}
/* looking from gun turret */
vw->vrp.x = tur->pos.x;
vw->vrp.y = tur->pos.y;
vw->vrp.z = tur->pos.z+5;
/* in firing direction */
vw->n.x = jcos(gun_angle) * jcos(drive->turret_ang);
vw->n.y = jsin(gun_angle) * jcos(drive->turret_ang);
vw->n.z = jsin(drive->turret_ang);
/* usual up vector */
vw->v.x = 0; vw->v.y = 0; vw->v.z = 1.0;
break;
case 7:
/* looking at vehicle, from close in */
vw->vrp.x=drive->parts[0]->pos.x + 50;
vw->vrp.y=drive->parts[0]->pos.y + 50;
vw->vrp.z=drive->parts[0]->pos.z + 50;
/* towards vehicle */
vw->n.x=-50;
vw->n.y=-50;
vw->n.z=-50;
/* up vector vertical */
vw->v.x=0; vw->v.y=0; vw->v.z=1;
break;
case 8:
/* looking from the viewpoint of the last shot fired, or
* forward view if none.
*/
if (drive->missile != -1) {
v = findbyvid(vhead,drive->missile);
}
if (!v) {
/* no missile found */
drive->missile = -1;
v=drive;
}
/* looking from projectile */
vw->vrp.x = v->parts[0]->pos.x;
vw->vrp.y = v->parts[0]->pos.y;
vw->vrp.z = v->parts[0]->pos.z;
/* in direction of travel */
vw->n.x = jcos(v->angle);
vw->n.y = jsin(v->angle);
vw->n.z = 0;
/* usual up vector */
vw->v.x = 0; vw->v.y = 0; vw->v.z = 1.0;
break;
case 9:
/* looking at an interesting thing */
v = findbyvid(vhead,drive->vm9vid);
if (!v) {
/* Vehicle being looked at is gone.. change to
* look at player's vehicle.
*/
/*
v = drive;
drive->vm9vid = drive->vid;
*/
drive->vm9vid = -1;
break;
}
/* looking at vehicle, from close in */
vw->vrp.x=v->parts[0]->pos.x + 50;
vw->vrp.y=v->parts[0]->pos.y + 50;
vw->vrp.z=v->parts[0]->pos.z + 50;
/* towards vehicle */
vw->n.x=-50;
vw->n.y=-50;
vw->n.z=-50;
/* up vector vertical */
vw->v.x=0; vw->v.y=0; vw->v.z=1;
break;
}
}
void printcontrols(void)
{
printf("Controls\n");
printf("--------\n");
printf("rotate left - %-8s",keyname(gkeys[0]));
printf("rotate right - %s\n",keyname(gkeys[1]));
printf("accellerate - %-8s",keyname(gkeys[2]));
printf("decellerate - %s\n",keyname(gkeys[3]));
printf("climb - %-8s",keyname(gkeys[4]));
printf("dive - %s\n",keyname(gkeys[5]));
printf("halt - %s\n",keyname(gkeys[6]));
printf("\n");
printf("gun left - %-8s",keyname(gkeys[7]));
printf("gun right - %s\n",keyname(gkeys[8]));
printf("gun up - %-8s",keyname(gkeys[15]));
printf("gun down - %s\n",keyname(gkeys[16]));
printf("fire - %-8s",keyname(gkeys[9]));
printf("lock on - %s\n",keyname(gkeys[12]));
printf("eject - %s\n",keyname(gkeys[13]));
printf("\n");
printf("quit - %s\n",keyname(gkeys[10]));
printf("wireframe toggle - %-8s",keyname(gkeys[11]));
printf("build menu toggle - %s\n",keyname(gkeys[14]));
printf("\n");
printf("long range view - 1 view from stationary point - 2\n");
printf("view from behind vehicle - 3 inside view - 4\n");
printf("above view - 5 turret view - 6\n");
printf("short range view - 7 missile view - 8\n");
printf("interesting thing view - 9\n");
}
/* read commands from the server to the client, and act on them
*/
double readnet(struct vehicle **vhead, struct object **ohead,
bool *winner, int *drvid)
{
char *msg; /* message received */
char *com; /* command part of message */
int veh; /* vehicle command is for */
double param; /* parameter of command */
struct vehicle *v; /* pointer to commanded vehicle */
double gtime; /* game time from server */
int i;
if (singlep) {
/* Messages come from the client, using a global string to fake
* sending through a file desciptor. */
msg=fakepipe;
}
else {
/* Message comes from the server. */
msg=ngets(sock);
}
#if NETDEBUG
printf("received \"%s\"\n",msg);
#endif
/* extract game time */
gtime=atof(strtok(msg," "));
/* extract commands from the message. each command is in the format
* <command> <vehicle id> <parameter>
* Repeat until there are no more commands in the message.
*/
while((com=strtok(NULL," "))) {
char *vehstr, *paramstr;
vehstr = strtok(NULL," ");
if (vehstr == NULL)
break;
veh = atoi(vehstr);
paramstr = strtok(NULL," ");
if (paramstr == NULL)
break;
param = atof(paramstr);
/* find the vehicle structure command is for */
v = findbyvid(*vhead,veh);
if (!v && com[0] != 'w') {
/* The vehicle this command is for has been destroyed..
* tough luck.
*/
continue;
}
/* perform action based on command and parameters */
switch(com[0]) {
case 'a':
rotatevehicle(v,param);
break;
case 'v':
/* new velocity */
v->velocity = param;
break;
case 'c':
/* new altitude */
shiftvehicle(v,0,0,param - v->parts[0]->pos.z);
break;
case 't':
/* new turret angle */
for(i=0; i<v->partcount; i++)
if (v->parts[i]->turret) {
rotatez(v->parts[i],param - v->parts[i]->angle);
v->parts[i]->angle = param;
}
break;
case 'f':
/* fire a shell */
fire(vhead,ohead,v);
break;
case 'x':
/* explode a vehicle */
v->hp = -1;
break;
case 'q':
/* game over */
printf("ALL PLAYERS DESTROYED... GAME OVER\n");
if (!singlep)
shutdown(sock,2);
close(sock);
exit(0);
case 'w':
/* someone has won the game */
*winner=true;
break;
case 'l':
/* a lock has been made */
v->lock = (int)param;
break;
case 'j':
/* a player has left their vehicle */
eject(vhead,ohead,v);
v->owner = o_none;
if (v->vid == *drvid) {
/* the ejected player is the current one!
* Change the player's vid to that of the
* new creature.
*/
*drvid = (*vhead)->vid;
}
break;
case 'b':
/* a player has construced something */
build(vhead,ohead,v,param);
break;
case 'r':
/* a player has raised/lowered their turret */
v->turret_ang = param;
break;
default:
printf("Unknown command from server!!\n");
exit(5);
}
}
if (singlep)
fakepipe[0] = '\0';
return gtime;
}
void controlvehicles(struct vehicle **vhead, struct object **ohead)
{
struct vehicle *v;
static int recalc=30; /* calls till next re-calculation */
/* of target or threat */
if (recalc-- == 0)
recalc=30;
for(v=*vhead; v; v=v->next) {
/* Use brain system if this vehicle has one.
*/
if (v->currentstate != -1 && v->owner == o_game) {
think(v,vhead,ohead);
continue;
}
if (v->target == -2) {
/* no possible targets. */
continue;
}
/* only consider vehicles controlled by the computer and
* potentially hostile.
*/
if (v->owner==o_game && v->type!=t_scenery && v->type!=t_static &&
v->type!=t_bullet && v->type!=t_shrapnel) {
struct vehicle *t=NULL;
/* find a target if this vehicle has none.
* Re-check this target every 30 frames, except for
* the case of missiles, which remain locked onto the
* one victim until they hit.
*/
if (v->target==-1 || (recalc==0 && v->type!=t_missile)) {
struct vehicle *p;
float mdis=VIEW_RANGE*VIEW_RANGE;
float dist;
/* find the closest possible target */
for(p=*vhead; p; p=p->next) {
if (possibletarget(v,p)) {
dist=vehicledist(v,p);
if (dist < mdis) {
mdis=dist;
t=p;
}
}
}
/* lock on if a target was found */
if (t) {
v->target=t->vid;
/*
printf("%s locked onto %s\n",v->code,t->code);
*/
}
}
else {
/* find the vehicle structure correspoding.
* to the target vid.
*/
t = findbyvid(*vhead,v->target);
}
if (!t) { /* no valid target found */
if (v->target == -1) {
/* no target was found last time either,
* so there can be none. give up looking.
*/
v->target=-2;
continue;
}
else {
v->target=-1;
continue;
}
}
/* computer-controlled vehicle/thing */
switch(v->type) {
case t_tank: {
/* adjust heading to head for a target, and
* fire a shot if close to the right angle
* and at the right height.
*/
v->angle_vel = vehicleangle(v,t)-v->angle;
if (v->angle_vel < -PI)
v->angle_vel += 2*PI;
v->velocity = v->max.velocity/2.0;
/* if pointing the right way ... */
if (dabs(v->angle_vel) < dtor(1.0)) {
/* ... and not flying too far above ... */
if (dabs(heightdiff(t,v)) < 5.0) {
/* ... fire a shot */
fire(vhead,ohead,v);
}
}
break;
}
case t_hover: {
/* adjust heading to approach target, and
* climb to it's altitude. fire when on line.
*/
v->angle_vel = vehicleangle(v,t) - v->angle;
if (v->angle_vel < -PI)
v->angle_vel += 2*PI;
v->velocity = 20;
v->climb = heightdiff(t,v);
v->velocity = v->max.velocity/2.0;
if (dabs(v->angle_vel) < dtor(0.1) &&
dabs(v->climb) < 5.0)
fire(vhead,ohead,v);
break;
}
case t_bird: {
/* run away from the nearest fish or player */
double awaydir;
awaydir = vehicleangle(v,t)+PI;
v->angle_vel = awaydir - v->angle;
if (v->angle_vel < -PI)
v->angle_vel += 2*PI;
else if (v->angle_vel > PI)
v->angle_vel -= 2*PI;
v->velocity = v->max.velocity;
break;
}
case t_fish: {
/* chase the nearest bird.
*/
v->angle_vel = vehicleangle(v,t) - v->angle;
if (v->angle_vel < -PI)
v->angle_vel += 2*PI;
v->climb = heightdiff(t,v)/3.0;
v->velocity = v->max.velocity;
break;
}
case t_missile: {
/* follow the target */
v->angle_vel = vehicleangle(v,t) - v->angle;
if (v->angle_vel < -PI)
v->angle_vel += 2*PI;
v->climb = heightdiff(t,v)/3.0;
v->velocity = v->max.velocity;
break;
}
case t_gunsite: {
/* rotate to target */
v->angle_vel = vehicleangle(v,t) - v->angle;
if (v->angle_vel < -PI)
v->angle_vel += 2*PI;
/* consider firing */
if (dabs(v->angle_vel) < dtor(1.0)) {
/* adjust firing angle upwards. */
v->turret_ang = atan2(heightdiff(t,v),
sqrt(vehicledist(t,v)));
if (dabs(v->turret_ang) < v->max.turret_ang)
fire(vhead,ohead,v);
}
break;
}
case t_shrapnel: /* Uncontrolled vehicles.
case t_static: */
case t_bullet:
case t_static:
case t_scenery:
case t_fixedwing:
case t_thing:
case t_tree:
case t_seedpod:
case t_mine:
case t_weapon:
case t_munitions:
break;
}
}
}
}
/* calculates the angle from vehicle s to vehicle d (in the x/y plane) */
double vehicleangle(struct vehicle *s, struct vehicle *d)
{
float xd,yd;
float ang;
xd = d->parts[0]->pos.x - s->parts[0]->pos.x;
yd = d->parts[0]->pos.y - s->parts[0]->pos.y;
ang=atan2(yd,xd);
return ang<0 ? ang+PI*2 : ang;
}
/* read key definitions in from the key configuration file.
*/
void readkeyfile(FILE *fp)
{
char *keynames[]={"left", "right", "accel", "decel", "climb",
"dive", "stop", "gunleft", "gunright",
"fire", "quit", "wireframe", "lock",
"eject", "menu", "gunup", "gundown", NULL};
printf("reading %s\n",KEYFILE);
while(!feof(fp)) {
char lbuf[100]=""; /* a line from the file */
char *comn; /* command key is for */
char *key; /* key code */
int i;
/* read in a line from the file */
fgets(lbuf,100,fp);
lbuf[strlen(lbuf)-1] = '\0';
if (!strlen(lbuf))
continue;
/* extract command from the line */
comn=strtok(lbuf," \t\n");
if (!comn) {
printf("you must give a command name on each line\n");
exit(1);
}
for(i=0; keynames[i] && strncmp(comn,keynames[i],
strlen(keynames[i])); i++)
;
if (!keynames[i]) {
printf("%s is not a valid command\n",comn);
printf("valid commands for keys are : \n");
for(i=0; keynames[i]; i++)
printf("%s ",keynames[i]);
printf("\n");
exit(1);
}
/* extract key assignment from line */
key=strtok(NULL," \t\n");
if (!key) {
printf("you must give a key for command %s\n",comn);
exit(5);
}
if (!strcmp(key,"return"))
gkeys[i]=XK_Return;
else if (!strcmp(key,"space"))
gkeys[i]=XK_space;
else if (!strcmp(key,"delete"))
gkeys[i]=XK_Delete;
else if (!strcmp(key,"escape"))
gkeys[i]=XK_Escape;
else if (!strcmp(key,"backspace"))
gkeys[i]=XK_BackSpace;
else if (!strcmp(key,"tab"))
gkeys[i]=XK_Tab;
else if (!strcmp(key,"left"))
gkeys[i]=XK_Left;
else if (!strcmp(key,"right"))
gkeys[i]=XK_Right;
else if (!strcmp(key,"up"))
gkeys[i]=XK_Up;
else if (!strcmp(key,"down"))
gkeys[i]=XK_Down;
else if (atoi(key))
gkeys[i]=atoi(key);
else
gkeys[i]=key[0];
}
}
/* return a description of a given XK code */
char *keyname(int k)
{
static char knbuf[20];
if (k > 32 && k < 128) {
/* key is a simple printable character */
sprintf(knbuf,"%c",k);
}
/* unprintable but named keys */
else if (k==XK_Return)
sprintf(knbuf,"return");
else if (k==XK_space)
sprintf(knbuf,"space");
else if (k==XK_Delete)
sprintf(knbuf,"delete");
else if (k==XK_Escape)
sprintf(knbuf,"escape");
else if (k==XK_BackSpace)
sprintf(knbuf,"backspace");
else if (k==XK_Tab)
sprintf(knbuf,"tab");
else if (k==XK_Left)
sprintf(knbuf,"left");
else if (k==XK_Right)
sprintf(knbuf,"right");
else if (k==XK_Up)
sprintf(knbuf,"up");
else if (k==XK_Down)
sprintf(knbuf,"down");
else {
/* key is an unknown character */
sprintf(knbuf,"ascii %d",k);
}
return knbuf;
}
bool possibletarget(struct vehicle *v, struct vehicle *targ)
{
/* prevent a vehicle locking onto itself */
if (v == targ)
return false;
/* find out what interests each vehicle type */
switch(v->type) {
case t_tank:
case t_hover:
/* armoured vehicles chase after the nearest player */
if (targ->owner==o_player || targ->owner==o_network)
return true;
break;
case t_fish:
/* fish chase after the nearest bird */
if (targ->type==t_bird)
return true;
break;
case t_bird:
/* birds fly away from fish */
if (targ->type == t_fish || targ->owner == o_player ||
targ->owner == o_network)
return true;
break;
case t_gunsite:
/* a gunsite shoots at any nearby vehicle, except for it's
* builder and other gunsites.
*/
if (targ->vid != v->buildervid && !boring(targ) &&
targ->type != t_gunsite)
return true;
break;
case t_shrapnel: /* Uncontrolled vehicles.
case t_static: */
case t_bullet:
case t_static:
case t_scenery:
case t_fixedwing:
case t_thing:
case t_tree:
case t_missile:
case t_seedpod:
case t_mine:
case t_weapon:
case t_munitions:
break;
}
return false;
}
void growtrees(struct vehicle **vh, struct object **oh)
{
struct vehicle *v, *vnext;
struct object *o;
int i,j;
static int call=0;
bool exploded;
for(v=*vh; v; v = vnext) {
vnext = v->next;
if (v->type == t_tree && (call=(call+1)%61) == 0) {
exploded=false;
for(i=0; i<v->partcount; i++) {
float maxht=0;
o = v->parts[i];
for(j=0; j<o->pcount; j++) {
o->points[j].z *= GROWTHRATE;
if (o->points[j].z > maxht)
maxht = o->points[j].z;
}
if (maxht > v->max.treeheight) {
/* Explode this tree! */
explode(vh,oh,v);
exploded = true;
break;
}
}
if (!exploded)
calcbbox(v);
}
}
}
/* build - a vehicle has just attemped to build something.
*
* vh - head of the vehicle list
* oh - head of the object list
* v - vehicle doing the building
* w - the type of thing it is attempting to build
*/
void build(struct vehicle **vh, struct object **oh, struct vehicle *v, int w)
{
struct vehicle *nv;
char wallname[100];
struct point pos;
int i;
/* check if the builder has enough resources */
if (v->res < wallcost[w])
return;
/* create a new vehicle structure, and add it to the list */
nv = (struct vehicle *)calloc(1,sizeof(struct vehicle));
nv->parts = (struct object **)calloc(MAX_PARTS_PER_VEHICLE,
sizeof(struct object *));
nv->next = *vh;
*vh = nv;
/* find the wall vehicle to copy from. Then copy it, and set it's
* attributes.
*/
sprintf(wallname,"wall%d",w);
copyvehicle(nv,findbycode(evhead,wallname),oh);
nv->code = strdupe("wall");
nv->owner = o_game;
nv->alive = true;
nv->vid = vidcount++;
nv->buildervid = v->vid;
/* rotate the new wall bit to line up in front of the player, and
* shift it out away from the player's vehicle.
*/
pos = v->parts[0]->pos;
pos.x += jcos(v->angle)*10;
pos.y += jsin(v->angle)*10;
for(i=0; i<nv->partcount; i++) {
rotatez(nv->parts[i],v->angle);
nv->parts[i]->pos.x += pos.x;
nv->parts[i]->pos.y += pos.y;
nv->parts[i]->pos.z += pos.z;
}
nv->angle += v->angle;
calcbbox(nv);
if (collide(nv,*vh)) {
/* uh, oh! This new wall section will collide with something
* already in place! Get rid of the new wall.
*/
freevehicle(nv,vh,oh);
XBell(display,30);
}
else {
/* success! charge the builder */
v->res -= wallcost[w];
}
}
/* boring - returns true if the vehicle given is only a minor player in
* the game, such as a bullet, house or fragment of shrapnel.
*/
bool boring(struct vehicle *v)
{
if (v->type == t_static || v->type == t_scenery || v->type == t_bullet ||
v->type == t_tree || v->type == t_seedpod || v->type == t_shrapnel ||
v->type == t_mine || v->type == t_munitions)
return true;
else
return false;
}
/* function to be called if ctrl-c is hit.
*/
void termhandler(int s)
{
ctrlc = 1;
}
/* xerrorhandler - called when a fatal X error occurs, typically due to
* a destroyed window.
*/
int xerrorhandler(Display *dis)
{
nprintf(sock,"d\n");
XFreePixmap(display,view_pm);
XFlush(display);
if (fork())
exit(0);
else
deadloop();
return 0;
}
/* Called after ctrl-c has been hit, to convince the server that this
* player is still active.
*/
void deadloop(void)
{
while(1) {
char *fromserv;
char *com;
/* send an empty line to convince the server that this player is
* still around. */
nprintf(sock,"\n");
/* soak up a line from the server.
*/
fromserv = ngets(sock);
strtok(fromserv," ");
while((com = strtok(NULL," "))) {
strtok(NULL," ");
strtok(NULL," ");
if (com[0] == 'q') {
/* game over */
shutdown(sock,2);
close(sock);
exit(0);
}
}
}
}